package component;

import Main.Main;
import org.fife.ui.rtextarea.RTextArea;
import ui.HomePage;
import util.FileUtils;
import util.GsonUils;
import util.ImageUtils;
import util.RunUtils;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.*;
import java.util.List;

/**
 * @author zhongwen
 * @description 顶部工具栏
 * @date 2021-12-22 15:41
 */
public class TopToolBar extends JToolBar {
    /**
     * 主页代码编辑面板，顶部工具栏的功能就是与其完成交互
     */
    private final TablePane tablePane;

    /**
     * 终端模拟框与主页代码编辑框二合一的垂直分割面板
     */
    private VerticalSplitPane vsp;

    private Deque<String> recentlyAdded = new ArrayDeque<>();


    private final Action newAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            tablePane.addClass();
        }
    };
    private final JButton newButton = new JButton(newAction);

    private final Action openAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            openFile();
        }
    };
    private final JButton openButton = new JButton(openAction);
    /**
     * 保存文件的事件
     */
    private final Action saveAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            saveFile();
        }
    };
    private final JButton saveButton = new JButton(saveAction);

    /**
     * 测试Java环境变量是否配置好的事件
     */
    private final Action testJDKAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            RunUtils.testJava(vsp);
        }
    };
    private final JButton testButton = new JButton(testJDKAction);

    /**
     * 编译TabPane当前选中的Java文件
     */
    private final Action complieAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            compile();
        }
    };
    private final JButton complieButton = new JButton(complieAction);
    /**
     * 指定命令编译TabPane当前选中的Java文件
     */
    private final Action complieCmdAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            compileCmd();
        }
    };
    private final JButton complieCmdButton = new JButton(complieCmdAction);

    /**
     * 运行TabPane当前选中的Java文件
     */
    private final Action runAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            run();
        }
    };
    private final JButton runButton = new JButton(runAction);

    /**
     * 指定命令运行TabPane当前选中的Java文件
     */
    private final Action runCmdAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            runCmd();
        }
    };
    private final JButton runCmdButton = new JButton(runCmdAction);
    /**
     * 运行任意dos终端命令
     */
    private final Action cmdAction = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            cmd();
        }
    };
    private final JButton cmdButton = new JButton(cmdAction);

    public TopToolBar(TablePane tablePane) {
        this.tablePane = tablePane;
        init();
    }

    public void setVsp(VerticalSplitPane vsp) {
        this.vsp = vsp;
    }


    private void init() {
        newButton.setIcon(new ImageIcon(ImageUtils.getImage("newFile.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        newButton.setToolTipText("新建文件(Ctrl+N)");

        openButton.setIcon(new ImageIcon(ImageUtils.getImage("openFileItem.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        openButton.setToolTipText("打开文件(Ctrl+O)");

        saveButton.setIcon(new ImageIcon(ImageUtils.getImage("saveFile.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        saveButton.setToolTipText("保存文件(Ctrl+S)");

        testButton.setIcon(new ImageIcon(ImageUtils.getImage("testJDK.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        testButton.setToolTipText("测试环境变量是否配置成功");

        complieButton.setIcon(new ImageIcon(ImageUtils.getImage("complie.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        complieButton.setToolTipText("编译(Alt+C)");

        runButton.setIcon(new ImageIcon(ImageUtils.getImage("run.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        runButton.setToolTipText("运行(Alt+R)");

        complieCmdButton.setIcon(new ImageIcon(ImageUtils.getImage("complieCmd.png", Main.configurationBean.getImageWidthAndHeight(), Main.configurationBean.getImageWidthAndHeight())));
        complieCmdButton.setToolTipText("指定命令编译");

        runCmdButton.setIcon(new ImageIcon(ImageUtils.getImage("runCmd.png",Main.configurationBean.getImageWidthAndHeight(),Main.configurationBean.getImageWidthAndHeight())));
        runCmdButton.setToolTipText("指定命令运行");

        cmdButton.setIcon(new ImageIcon(ImageUtils.getImage("cmd.png",Main.configurationBean.getImageWidthAndHeight(),Main.configurationBean.getImageWidthAndHeight())));
        cmdButton.setToolTipText("运行终端命令");
        this.add(newButton);
        this.addSeparator();
        this.add(openButton);
        this.addSeparator();
        this.add(saveButton);
        this.setOrientation(HORIZONTAL);
        this.addSeparator(new Dimension(200, 0));
        this.addSeparator();
        this.add(testButton);
        this.addSeparator();
        this.add(complieButton);
        this.addSeparator();
        this.add(runButton);
        this.addSeparator();
        this.add(complieCmdButton);
        this.addSeparator();
        this.add(runCmdButton);
        this.addSeparator();
        this.add(cmdButton);
        this.setFloatable(false);
    }

    public Deque<String> getRecentlyAdded() {
        return recentlyAdded;
    }

    /**
     * 打开文件的真实逻辑
     */
    public void openFile() {
        // 带后缀名过滤器
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Java源文件(*.java)", "java");
        JFileChooser openChooser = new JFileChooser(Main.configurationBean.getNowPath());
        openChooser.setFileFilter(filter);
        openChooser.setMultiSelectionEnabled(true);
        int showOpenDialog = openChooser.showOpenDialog(HomePage.jf);
        // 选择了打开的按钮
        if (showOpenDialog == JFileChooser.OPEN_DIALOG) {
            File[] selectedFiles = openChooser.getSelectedFiles();
            // 保证一个文件只能显示在一个选项页面中
            int tabCount = tablePane.getTabCount();
            Map<File, Integer> map = new HashMap<>();
            for (int i = 0; i < tabCount; i++) {
                ClassTab classTab = (ClassTab) tablePane.getTabComponentAt(i);
                if (classTab.getTextFile() != null) {
                    map.put(classTab.getTextFile(), i);
                }
            }
            if (selectedFiles != null) {
                for (File f : selectedFiles) {
                    if (map.containsKey(f)) {
                        tablePane.setSelectedIndex(map.get(f));
                    } else {
                        ClassTab tab = tablePane.addAndReturnClass();
                        JavaEditorPane javaText = (JavaEditorPane) tablePane.getComponentAt(tablePane.indexOfTabComponent(tab));
                        System.out.println("现在打开文件的绝对路径为：" + f.getAbsolutePath());
                        tab.setTextFile(f);
                        tab.changeFileName(f.getName());
                        RTextArea textArea = javaText.getTextArea();
                        String charset = FileUtils.getFileEncode(f);
                        System.out.println("现在打开的文本编码为" + charset);
                        List<String> temp = FileUtils.openFilesWithList(f, charset);
                        StringBuilder openFileString = new StringBuilder();
                        for (int i = 0; i < temp.size() - 1; i++) {
                            openFileString.append(temp.get(i) + "\n");
                        }
                        if (temp.size() > 0) {
                            openFileString.append(temp.get(temp.size() - 1));
                        }
                        textArea.setText(openFileString.toString());
                        textArea.requestFocus();
                        if (recentlyAdded.size() >= 5) {
                            recentlyAdded.poll();
                            recentlyAdded.addLast(f.getAbsolutePath());
                        } else {
                            recentlyAdded.addLast(f.getAbsolutePath());
                        }
                    }
                }
                // 将修改的默认打开文件目录保存到配置文件中
                System.out.println(openChooser.getCurrentDirectory().toString());
                Main.configurationBean.setNowPath(openChooser.getCurrentDirectory().toString());
                GsonUils.objectToString(Main.configurationBean);
            }
        }
    }

    /**
     * 保存文件的真实逻辑
     */
    public void saveFile() {
        // 带后缀名过滤器
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Java源文件(*.java)", "java");
        // 当前选中的编辑页面
        JavaEditorPane selectedText = (JavaEditorPane) tablePane.getSelectedComponent();
        if (selectedText == null) {
            JOptionPane.showMessageDialog(HomePage.jf, "请新建文件！");
            return;
        }
        // 当前选中的选项卡
        int selectedIndex = tablePane.getSelectedIndex();
        ClassTab selectedTab = (ClassTab) tablePane.getTabComponentAt(selectedIndex);

        // 当前文件为untitiled+i
        if (selectedTab.getTextFile() == null) {
            String text = selectedText.getTextArea().getText();
            JFileChooser saveFile = new JFileChooser(Main.configurationBean.getNowPath()) {
                @Override
                public void approveSelection() {
                    File selectedFile = this.getSelectedFile();
                    if (selectedFile != null) {
                        String name = selectedFile.getName();
                        if (!name.contains(".java") && this.getFileFilter().equals(filter)) {
                            selectedFile = new File(this.getCurrentDirectory() + "/" + name + ".java");
                            name = selectedFile.getName();
                        } else {
                            selectedFile = new File(this.getCurrentDirectory() + "/" + name);
                            name = selectedFile.getName();
                        }
                        if (selectedFile.exists()) {
                            int i = JOptionPane.showConfirmDialog(HomePage.jf, "是否替换已存在的" + "\"" +
                                    selectedFile.getAbsolutePath() + "\"", "CodeEasy", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null);
                            if (i == JOptionPane.YES_OPTION) {
                                FileUtils.saveFile(selectedFile, text, BottomBar.encodeButton.getText());
                                selectedTab.changeFileName(name);
                                selectedTab.setTextFile(selectedFile);
                                super.approveSelection();
                            }
                        } else {
                            FileUtils.saveFile(selectedFile, text, BottomBar.encodeButton.getText());
                            selectedTab.changeFileName(name);
                            selectedTab.setTextFile(selectedFile);
                            super.approveSelection();
                        }
                    }
                }
            };
            System.out.println(this.getClass() + Main.configurationBean.getNowPath());
            saveFile.setFileFilter(filter);
            // 设置默认的文件名
            String name = FileUtils.getDefaultName(text);
            System.out.println("需保存文件的默认名字 ： " + name);
            if (name != null) {
                saveFile.setSelectedFile(new File(name));
            } else {
                saveFile.setSelectedFile(new File(selectedTab.getFileName()));
            }
            saveFile.showSaveDialog(HomePage.jf);
            // 将修改的默认打开文件目录保存到配置文件中
            Main.configurationBean.setNowPath(saveFile.getCurrentDirectory().toString());
            GsonUils.objectToString(Main.configurationBean);
        } else {
            // 二次保存的情况
            String text = selectedText.getTextArea().getText();
            FileUtils.saveFile(selectedTab.getTextFile(), text, BottomBar.encodeButton.getText());
        }

    }

    /**
     * 编译的真实逻辑
     */
    public void compile() {
        if (tablePane.getSelectedIndex() == -1) {
            JOptionPane.showMessageDialog(HomePage.jf, "请选择文件！", "提醒", JOptionPane.PLAIN_MESSAGE, null);
            return;
        }
        ClassTab selectedClass = (ClassTab) tablePane.getTabComponentAt(tablePane.getSelectedIndex());
        selectedClass.needSaveFile();
        File f = selectedClass.getTextFile();
        RunUtils.compileJava(f, vsp);
    }
    /**
     * 指定命令编译的真实逻辑
     */
    public void compileCmd() {
        if (tablePane.getSelectedIndex() == -1) {
            JOptionPane.showMessageDialog(HomePage.jf, "请选择文件！", "提醒", JOptionPane.PLAIN_MESSAGE, null);
            return;
        }
        ClassTab selectedClass = (ClassTab) tablePane.getTabComponentAt(tablePane.getSelectedIndex());
        selectedClass.needSaveFile();
        File f = selectedClass.getTextFile();
        Object o = JOptionPane.showInputDialog(HomePage.jf, "编译命令（工作目录为选定文件的父目录）", "命令输入", JOptionPane.PLAIN_MESSAGE, null, null, "javac -encoding utf-8");
        if(o != null) {
            RunUtils.compileJava(f, (String) o, vsp);
        }
    }
    /**
     * 运行的真实逻辑
     */
    public void run() {
        if (tablePane.getSelectedIndex() == -1) {
            JOptionPane.showMessageDialog(HomePage.jf, "请选择文件！", "提醒", JOptionPane.PLAIN_MESSAGE, null);
            return;
        }
        ClassTab selectedClass = (ClassTab) tablePane.getTabComponentAt(tablePane.getSelectedIndex());
        File f = selectedClass.getTextFile();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("运行子线程进行中：");
                RunUtils.runJava(f, vsp);
            }
        }).start();

    }
    /**
     * 指定命令运行的真实逻辑
     */
    public void runCmd() {
        if (tablePane.getSelectedIndex() == -1) {
            JOptionPane.showMessageDialog(HomePage.jf, "请选择文件！", "提醒", JOptionPane.PLAIN_MESSAGE, null);
            return;
        }
        ClassTab selectedClass = (ClassTab) tablePane.getTabComponentAt(tablePane.getSelectedIndex());
        File f = selectedClass.getTextFile();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("运行子线程进行中：");
                Object o = JOptionPane.showInputDialog(HomePage.jf, "运行命令（工作目录为选定文件的父目录）", "命令输入", JOptionPane.PLAIN_MESSAGE, null, null, "java ");
                if(o != null) {
                    RunUtils.runJava(f, (String) o, vsp);
                }
            }
        }).start();
    }
    /**
     * 运行任意dos终端命令
     */
    public void cmd(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("运行子线程进行中：");
                Object o = JOptionPane.showInputDialog(HomePage.jf, "运行命令（工作目录为配置文件中nowPath)\n多条cmd命令由&&连接",
                        "命令输入", JOptionPane.PLAIN_MESSAGE, null, null, "java ");
                if(o != null) {
                    RunUtils.runCmd((String) o, vsp);
                }
            }
        }).start();
    }
}
